<style scoped>
.logic-flow,
.container {
  width: 100%;
  height: 100%;
}
.header {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  padding: 0 20px;
  width: 100%;
  height: 50px;
  color: white;
  background: var(--primary);
}

.header .left {
  color: white;
  font-size: 16px;
}

.header .left .iconfont {
  vertical-align: middle;
  font-size: 30px;
}

.header .left .title {
  margin: 0 20px;
  font-weight: bold;
}
</style>

<template>
  <div class="logic-flow">
    <div class="header">
      <div class="left">
        <span class="iconfont icon-31fanhui1"></span>
        <span class="title">编辑里程 - 方案名称</span>
      </div>
      <div class="right">
        <a-button class="btn">保存</a-button>
      </div>
    </div>
    <div class="container" ref="container"></div>

    <!-- 节点面板 -->
    <NodePanel
      v-if="lf"
      :lf="lf"
      :panelList="panelList"
      @rowClick="handlePanel"
    />

    <!-- 添加节点 -->
    <NodeDialog
      ref="NodeDialog"
      v-if="nodeVisible"
      :visible="nodeVisible"
      @close="handleCloseNode"
      @submit="handleSubmitNode"
    />

    <!-- 添加任务 -->
    <TaskDialog
      ref="TaskDialog"
      v-if="taskVisible"
      :visible="taskVisible"
      @close="handleCloseTask"
      @submit="handleSubmitTask"
    />
  </div>
</template>

<script>
import {  Menu, DndPanel } from '@logicflow/extension'
import LogicFlow from "@logicflow/core";
import NodePanel from './LF/NodePanel'
import NodeDialog from './SettingDialog/NodeDialog';
import TaskDialog from './SettingDialog/TaskDialog.vue';
import TaskNode from './Node/TaskNode.js';
import TaskItem from './Node/TaskItem.js';
import ExpandNode from './Node/ExpandNode.js';
import MyGroup from "./Node/MyGroup";
import CurvedEdge from './Edge/CurvedEdge'
import "./style.css";
import flowData from './flowData.js';
import { panelList } from './config'
import { Storage, guid } from '@/utils/util'

export default {
  name: 'LF',
  data() {
    return {
      lf: null, // 实例对象
      panelList, // 面板列表
      panelAction: [], // 面板操作
      record: {}, // 当前节点记录
      flowData, // 所有节点
      nodeVisible: false, //添加节点弹层
      taskVisible: false, //添加任务弹层
      nodeGroupMap: new Map()
    }
  },
  components: {
    NodePanel,
    NodeDialog,
    TaskDialog
  },
  mounted() {
    // 本地存储
    Storage.set('flowData', flowData)
    // 注册菜单
    LogicFlow.use(Menu)
    // 注册控制面板
    LogicFlow.use(DndPanel)
    // 实例化
    this.lf = new LogicFlow({
      container: this.$refs.container,
      isSilentMode: false, // 静默模式
      background: {
        backgroundColor: '#F5F7FA'
      }
    });
    
    // console.log(this.incoming.edges.concat(this.outgoing.edges);)

    // 注册节点
    this.registerNode()
  },
  methods: {
    /**
     * @func registerNode
     * @description 注册节点
     */
    registerNode() {
      // 任务节点
      this.lf.register(TaskNode);
      // 任务
      this.lf.register(TaskItem);
      // 伸缩节点
      this.lf.register(ExpandNode);
      // 分组
      this.lf.register(MyGroup);
      // 自定义边
      this.lf.register(CurvedEdge);
      this.lf.setDefaultEdgeType("CurvedEdge");

      // 渲染
      this.render()
    },

    /**
     * @func render
     * @description 渲染节点
     */
    render () {
      this.lf.render(this.flowData);

      // 事件
      this.handleEvent()
    },

    /**
     * @func handleEvent
     * @description 操作事件
     */
    handleEvent() {
      // 节点单击
      this.lf.on('node:click', ({data}) => {
        // console.log('node:click', data)
        if (data.type === 'node' || data.type=== 'task') {
          this.panelList.map(item => {
            item.disabled = true
          })
          this.record = data
          this.panelAction = data.properties.permission
          this.panelList.map(item => {
            if(this.panelAction.includes(item.type)) {
              item.disabled = false
            }
          })
          console.log(this.record.properties)
          if (this.record.properties.children.length <= 1) {
            this.panelList.map(item => {
              if(this.panelAction.includes(['up', 'down'])) {
                item.disabled = false
              }
            })
          }
        }

        /// 展开/收缩节点监听
        if (data.type === 'expand') {
          this.toggleExpand(data)
          // let children = [];
          // if (data.properties.isExpand) {
          //   console.log(111)
          //   this.flowData.nodes.map((item) => {
          //     console.log(item.id, data.properties.isExpand)
          //     if (item.id === data.properties.parent_id) {
          //       console.log(item, 199)
          //       children = item.properties.children

          //       this.flowData.nodes.map((item) => {
          //         if (children.includes(item.id)) {
          //           // this.flowData.nodes.splice(index, 1)
          //           // this.graphModel.deleteNode(item.id);
          //         }
          //       })
          //     }
          //   })
          // }
          // this.lf.render(flowData);
        }
      })

      // 外部拖入节点添加时触发
      this.lf.on('node:dnd-add', ({data}) => {
        console.log('node:dnd-add: ', data);
        setTimeout(() => {
          this.nodeVisible = true
        }, 500);
      })

      this.lf.on('edge:click', ({data}) => {
        console.log('edge:click', data)
        //  this.$data.clickNode = data
        //   this.$data.dialogVisible = true
      })

      // this.lf.on('element:click', () => {
      //   console.log('element:click')
      // })

      this.lf.on('edge:add', ({data}) => {
        console.log('edge:add', data)
      })
      this.lf.on('node:mousemove', ({data}) => {
        if (data.properties.parent_id !== undefined) return false
        console.log('node:mousemove', data)
        // this.moveData = data
      })

      /**
       * @description 空点击事件
       */
      this.lf.on('blank:click', () => {
        console.log('blank:click')
        this.handleReset()
      })

      this.lf.on('connection:not-allowed', (data) => {
        console.log('connection:not-allowed', data)
        // this.$message({
        //   type: 'error',
        //   message: data.msg
        // })
      })

      // 自定义节点编辑
      this.lf.on('task:edit', (item) => {
        this.nodeVisible = true
        this.$nextTick(() => {
          this.$refs.NodeDialog.setRecord(item, 'edit')
        })
      })

      // 自定义任务编辑
      this.lf.on('taskItem:edit', (item) => {
        this.taskVisible = true
        this.$nextTick(() => {
          this.$refs.TaskDialog.setRecord(item, 'edit')
        })
      })

      // 自定义节点删除
      this.lf.on('task:delete, taskItem:delete', (record) => {
        console.log('task:delete: ', record);
        const { flowData } = this
        flowData.nodes.map((item, index) => {
          if (item.id === record.id) {
            flowData.nodes.splice(index,1);
          }
        })
        Storage.set('flowData', flowData)
        this.lf.render(flowData);
      })

    },

    /**
     * @func toggleExpand
     * @param { Object } record 当前记录
     * @description 展开收缩切换
     */
    toggleExpand(record) {
      /// 更新节点
      flowData.nodes.map((item) => {
        // 更新当前节点状态
        if (item.id === record.id) {
          item.properties.isExpand = !item.properties.isExpand
        }

        // 更新父级节点状态
        if(item.id === record.properties.parent_id) {
          item.properties.isExpand = !item.properties.isExpand

          /// 更新子节点
          item.properties.children.map(child => {
            child.properties.isShow = !child.properties.isShow
          })
        }
      })

      // 隐藏同级父节点连接边
      flowData.edges.map(item => {
        if (item.sourceNodeId === record.properties.parent_id) {
          item.properties.isShow = !item.properties.isShow
        }
      })

      this.lf.render(flowData);
    },

    /**
     * @func handlePanel
     * @param { Object } item
     * @description 左侧操作面板
     */
    handlePanel(item) {
      // console.log('handlePanel:', item);
      if (!item.disabled) this[`handle${item.type.slice(0, 1).toUpperCase() + item.type.slice(1).toLowerCase()}`]()
    },

    /**
     * @func handleUp
     * @description  上移
     */
    handleUp() {
      const { flowData, record } = this
      flowData.nodes.map((item) => {
        if (item.id === record.id) {
          console.log(item.properties.children.length)
        }
      })
    },

    /**
     * @func handleBefore
     * @description 之前插入
     */
    handleBefore() {
      console.log('handleBefore: handleBefore');
      const { flowData, record } = this
      let isFlag = true;
      flowData.nodes.map((item, index) => {
        if (item.id === record.id && isFlag) {
          isFlag = false
          const item = {
            id: guid(),
            type: "task",
            x: 300,
            y: record.y - 100,
            properties: {
              type: 'init',
              children: [],
              name: "添加节点",
              num: flowData.nodes.length + 1,
              permission: ['before', 'after', 'child', 'task']
            }
          }
          this.record = item
          flowData.nodes.splice(index - 1, 0, item);

          // 遍历同级节点之前插入统一改变y轴
          flowData.nodes.map((c) => {
            if (c.y <= item.y && item.id !== c.id) {
              c.y -= 100
            }
          })
          this.lf.render(flowData);

          // 节点添加完成后弹出修改弹框
          setTimeout(() => {
            this.nodeVisible = true
            this.$nextTick(() => {
              this.$refs.NodeDialog.setRecord(item)
            })
          }, 500);
          return false
        }
      })
    },

    /**
     * @func handleBefore
     * @description 之后插入
     */
    handleAfter() {
      console.log('handleAfter: handleAfter');
      const { flowData, record } = this
      flowData.nodes.map((item, index) => {
        if (item.id === record.id) {
          const item = {
            id: guid(),
            type: "task",
            x: 300,
            y: record.y + 100,
            properties: {
              type: 'init',
              children: [],
              name: "添加节点",
              num: flowData.nodes.length + 1,
              permission: ['before', 'after', 'child', 'task']
            }
          }
          this.record = item
          flowData.nodes.splice(index + 1, 0, item);

          // 遍历同级节点之后插入统一改变y轴
          flowData.nodes.map((c) => {
            if (c.y >= item.y && item.id !== c.id) {
              c.y += 100
            }
          })
          this.lf.render(flowData);

          // 节点添加完成后弹出修改弹框
          setTimeout(() => {
            this.nodeVisible = true
            this.$nextTick(() => {
              this.$refs.NodeDialog.setRecord(item)
            })
          }, 500);
        }
      })
    },

    /**
     * @func handleChild
     * @description 添加子级
     */
    handleChild() {
      const { flowData, record } = this
      console.log(`父节点 ->`, record)
      flowData.nodes.map((item) => {
        if (item.id === record.id) {
          const taskItem = {
            id: guid(),
            type: "task",
            x: record.x + 340,
            y: record.y + (item.properties.children.length * 100),
            properties: {
              parent_id: record.id,
              parent: record,
              type: 'init',
              children: [],
              name: "添加节点",
              num: `${record.properties.num} - ${record.properties.children.length + 1}`,
              permission: ['before', 'after', 'child', 'task', 'rchild', 'up', 'down']
            }
          }
          item.properties.children.push(taskItem)
          // 更新父节点默认展开
          item.properties.isExpand = true
          this.record = record
          flowData.nodes.push(taskItem);

          // // 遍历同级节点之后插入统一改变y轴
          // flowData.nodes.map((c) => {
          //   if (c.y >= item.y && item.id !== c.id) {
          //     c.y += 100
          //   }
          // })

          this.lf.render(flowData);

          // 节点添加完成后弹出修改弹框
          setTimeout(() => {
            this.nodeVisible = true
            this.$nextTick(() => {
              this.$refs.NodeDialog.setRecord(taskItem)
            })
          }, 500);
        }
      })
    },

    /**
     * @func handleTask
     * @description 添加任务
     */
    handleTask() {
      const { flowData, record } = this
      flowData.nodes.map((item) => {
        if (item.id === record.id) {
          const taskItem = {
            id: guid(),
            type: "taskItem",
            x: record.x + 340,
            y: record.y + (item.properties.children.length * 100),
            properties: {
              parent_id: record.id,
              parent: record,
              type: 'init',
              children: [],
              name: "添加任务",
              permission: ['up', 'down', 'before', 'after', 'rtask']
            }
          }

          item.properties.children.push(taskItem)
          // 更新父节点默认展开
          item.properties.isExpand = true
          this.record = record
          flowData.nodes.push(taskItem);

          // // 遍历同级节点之后插入统一改变y轴
          // flowData.nodes.map((c) => {
          //   if (c.y >= item.y && item.id !== c.id) {
          //     c.y += 100
          //   }
          // })
          this.lf.render(flowData);

          // // 节点添加完成后弹出修改弹框
          setTimeout(() => {
            this.taskVisible = true
            this.$nextTick(() => {
              this.$refs.TaskDialog.setRecord(taskItem)
            })
          }, 500);
        }
      })
    },

    /**
     * @func queryParentNode
     * @description 查询树节点
     */
    queryParentNode (node, pId, temp = undefined) {
      const forFn = (arr, id) => {
        for (let i = 0; i < arr.length; i++) {
          if (arr[i].id === id) {
            temp = arr[i] // 查询父级节点
            break
          } else {
            if (arr[i].children) {
              forFn(arr[i].children, id)
            }
          }
        }
      }
      forFn(node, pId)
      return temp
    },

    /**
     * @func handleCloseNode
     * @description 关闭节点
     */
    handleCloseNode(record) {
      console.log('handleCloseNode: ', record);
      if (record.properties.type === 'init') {
        const { flowData } = this
        flowData.nodes.map((item, index) => {
          if (item.id === record.id) {
            flowData.nodes.splice(index,1);
          }
        })
        this.lf.render(flowData);
      }
      this.handleReset()
    },

    /**
     * @func handleSubmitNode
     * @description 任务节点提交回调
     */
    handleSubmitNode(record) {
      console.log('handleSubmitNode: ', record);

      const { flowData } = this

      // 插入节点
      flowData.nodes.map((item, index) => {
        if (item.id === record.id) {
          flowData.nodes.splice(index, 1, record);
        }
      })

      // 父节点 -> 收缩/展开 连接线
      flowData.edges.push({
        id: guid(),
        type: "CurvedEdge",
        sourceNodeId: record.properties.parent_id,
        targetNodeId: record.id,
        properties: {
          parent_id: record.properties.parent_id,
          parent: record.properties.parent,
          isShow: true
        }
      })

      // 判断父节点是否包含子级，包含的话添加展开节点
      if (record.properties.parent.properties.children.length === 0) {
        const expand_id = guid()
        flowData.edges.push({
          id: guid(),
          type: "CurvedEdge",
          sourceNodeId: record.properties.parent_id,
          targetNodeId: expand_id,
          properties: {
            parent_id: record.properties.parent_id,
            parent: record.properties.parent,
            type: 'expand',
            isShow: true
          }
        })

        flowData.nodes.push({
          id: expand_id,
          type: "expand",
          x: record.x  - 185,
          y: record.y,
          properties: {
            parent_id: record.properties.parent_id,
            parent: record.properties.parent,
            isExpand: true
          }
        })
      }

      // 子节点默认展开显示
      flowData.nodes.map(item => {
        if (item.id === record.properties.parent_id) {
          const currParent = item
          currParent.properties.children.map(child => {
            child.properties.isShow = true
          })
        }
      })

      Storage.set('flowData', flowData)
      this.lf.render(flowData);
      this.handleReset()
    },

    /**
     * @func handleCloseNode
     * @description 关闭节点
     */
    handleCloseTask(record) {
      console.log('handleCloseTask: ', record);
      if (record.properties.type === 'init') {
        const { flowData } = this
        flowData.nodes.map((item, index) => {
          if (item.id === record.id) {
            flowData.nodes.splice(index,1);
          }
        })
        this.lf.render(flowData);
      }
      this.handleReset()
    },

    /**
     * @func handleSubmitTask
     * @description 提交
     */
    handleSubmitTask(record) {
      console.log('handleSubmitTask: ', record);
      const { flowData } = this
      flowData.nodes.map((item, index) => {
        if (item.id === record.id) {
          flowData.nodes.splice(index, 1, record);
        }
      })
      // flowData.nodes.push({
      //   id: new Date(),
      //   type: "expand",
      //   baseType: "node",
      //   x: 450,
      //   y: 210,
      //   properties: {}
      // })

      // 连接线
      flowData.edges.push({
        id: guid(),
        type: "CurvedEdge",
        sourceNodeId: record.properties.parent_id,
        targetNodeId: record.id,
        properties: {
          isShow: true
        }
      })

      Storage.set('flowData', flowData)
      this.lf.render(flowData);
      this.handleReset()
    },

    /**
     * @func handleReset
     * @description 重置
     */
    handleReset() {
      this.nodeVisible = false
      this.taskVisible = false
      this.record = {}
      this.panelAction = []
      this.panelList.map(item => {
        item.disabled = true
      })
    }
  }
};
</script>